package com.zch.rpc.service.server;



import com.zch.rpc.client.common.model.RequestModel;
import com.zch.rpc.client.common.model.ResponseModel;

import java.io.*;
import java.lang.reflect.Method;
import java.net.Socket;
import java.util.Map;

/**
 * 用线程来异步执行socket操作（一定程度上提升并发性能）
 *
 */
public class ServiceTask implements Runnable{
	
	private Socket client;
	private Map<String,Object> services;//接口名跟目标对象的map
	
	/**
	 * @param client 客户端
	 * @param services 所有服务
	 */
	public ServiceTask(Socket client, Map<String, Object> services) {
		super();
		this.client = client;
		this.services = services;
	}



	public void run() {
		InputStream in = null;
		ObjectInputStream oin = null;
		OutputStream out = null;
		ObjectOutputStream oout = null;
		ResponseModel response = new ResponseModel();
		try {
			// 1. 获取流
			in = client.getInputStream();
			oin = new ObjectInputStream(in);
			out = client.getOutputStream();
			oout = new ObjectOutputStream(out);
			
			// 2. 获取请求数据，强转参数类型
			Object param = oin.readObject();
			RequestModel request = null;
			if(!(param instanceof RequestModel)){
				response.setError(new Exception("参数错误"));
				oout.writeObject(response);
				oout.flush();
				return;
			}else{
				request = (RequestModel) param;
			}
			
			// 3. 查找并执行服务方法（找到接口的实现类实例对象）
			Object service = services.get(request.getInterfaceName());
			Class<?> clazz= service.getClass();
			//根据参数名和参数类型一起定位出目标方法（通过反射来调用目标对象。）
			Method method = clazz.getMethod(request.getMethodName(), request.getParamTypes());
			Object result = method.invoke(service, request.getParams());
			// 4. 得到结果并返回
			response.setResult(result);
			oout.writeObject(response);
			oout.flush();
			return;
		} catch (Exception e) {
			try {	//异常处理
				if(oout != null){
					response.setError(e);
					oout.writeObject(response);
					oout.flush();
				}
			} catch (Exception e1) {
				e1.printStackTrace();
			}
			return;
		}finally{
			try {	// 关闭流
				if(in != null) in.close();
				if(oin != null) oin.close();
				if(out != null) out.close();
				if(oout != null) oout.close();
				if(client != null) client.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}

}
